/**
 ************************************************************************************************************
 * File describing a camera: Camera is supposed to be oriented in a Right, Up, Back coordinate system
 * (X,Y,Z right handed)
 ************************************************************************************************************
 * @file RBCamera.h
 ************************************************************************************************************/

#ifndef __RBCAMERA__H__
#define __RBCAMERA__H__

#ifdef  HEADER_ONCE
#pragma HEADER_ONCE
#endif

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBCamera.h)
#endif

/************************************************************************************************************
 * Includes
 ************************************************************************************************************/
#include "RBEntity.h"
#include "RBTSpatialComponent.h"

#include "RBMatrix.h"

/************************************************************************************************************
 * Forward declarations
 ************************************************************************************************************/
class RBStream;

/************************************************************************************************************
 * Class
 ************************************************************************************************************/
RBDeclareHandle(RBCamera);

class RBCamera : public RBTSpatialComponent<RBCamera>
{
public:
    RB_DECLARE_COMPONENT(RBCamera)

				        RBCamera		    (RBEntityHandle entityHandle, RBTransformComponentHandle xForm = InvalidHandle);
	virtual		       ~RBCamera		    ();

    static float4x4     LookAtDirection     (const float3& vDirection, const float3& vUp);
    static float4x4     BuildProjMatrix     (const RBCamera& camera);

    float4x4            GetViewMatrix       () const;
    float4x4            GetProjMatrix       () const;
    bool                HasCustomProj       () const { return m_bCustomProj; };

    float3              GetWorldDirection   () const;
    float3              GetWorldUp          () const;
    float3              GetWorldRight       () const;

    void                LookAt              (const float3& vDirection, const float3& vUp);

    void                SetViewFrustum      (float32 fFovY, float32 fAspectRatio, float32 fNear, float32 fFar, bool bOrtho);
    void                SetViewFrustum      (float32 fLeft, float32 fRight, float32 fTop, float32 fBottom, float32 fNear, float32 fFar, bool bOrtho);
    void                ChangeAspectRatio   (float32 fAspectRatio);

    virtual void        Serialize           (RBStream& kStream);

    float32             Left                () const;
    float32             Right               () const;
    float32             Top                 () const;
    float32             Bottom              () const;
    float32             Near                () const;
    float32             Far                 () const;
    bool                Ortho               () const;

    void                EnableCustomProj    (const float4x4& customProj);
    void                DisableCustomProj   ();

    void                copy_members        (RBCamera* dest);

    enum Direction
    {
        CD_RIGHT = 0,
        CD_UP,
        CD_BACK
    };

protected:
    float32             m_fLeft;
    float32             m_fRight;
    float32             m_fTop;
    float32             m_fBottom;
    float32             m_fNear;
    float32             m_fFar;
    bool                m_bOrtho;

    bool                m_bCustomProj;
    float4x4            m_customProj;

};

RBDeclareSmartPointer(RBCamera);

#include "RBCamera.inl"

/************************************************************************************************************/

#endif // __RBCAMERA__H__
